package main

import (
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"

	"nettools/shared/models"
)

// ClientConfigManager 客户端配置管理器
type ClientConfigManager struct {
	config   *models.ClientConfig
	filePath string
}

// NewClientConfigManager 创建客户端配置管理器
func NewClientConfigManager(configPath string) *ClientConfigManager {
	return &ClientConfigManager{
		filePath: configPath,
		config:   models.DefaultClientConfig(),
	}
}

// LoadConfig 加载配置文件
func (cm *ClientConfigManager) LoadConfig() error {
	if cm.filePath == "" {
		// 如果没有指定配置文件，使用默认配置
		return nil
	}

	// 检查文件是否存在
	if _, err := os.Stat(cm.filePath); os.IsNotExist(err) {
		// 文件不存在，创建默认配置文件
		return cm.SaveConfig()
	}

	// 读取文件内容
	data, err := os.ReadFile(cm.filePath)
	if err != nil {
		return fmt.Errorf("读取配置文件失败: %w", err)
	}

	// 验证是否为JSON格式
	ext := filepath.Ext(cm.filePath)
	if ext != ".json" {
		return fmt.Errorf("不支持的配置文件格式: %s，仅支持JSON格式", ext)
	}

	// 解析JSON配置
	err = json.Unmarshal(data, cm.config)
	if err != nil {
		return fmt.Errorf("解析配置文件失败: %w", err)
	}

	return cm.validateConfig()
}

// SaveConfig 保存配置到文件
func (cm *ClientConfigManager) SaveConfig() error {
	if cm.filePath == "" {
		return fmt.Errorf("未指定配置文件路径")
	}

	// 确保目录存在
	dir := filepath.Dir(cm.filePath)
	if err := os.MkdirAll(dir, 0755); err != nil {
		return fmt.Errorf("创建配置目录失败: %w", err)
	}

	// 验证是否为JSON格式
	ext := filepath.Ext(cm.filePath)
	if ext != ".json" {
		return fmt.Errorf("不支持的配置文件格式: %s，仅支持JSON格式", ext)
	}

	// 序列化为JSON格式
	data, err := json.MarshalIndent(cm.config, "", "  ")
	if err != nil {
		return fmt.Errorf("序列化配置失败: %w", err)
	}

	// 写入文件
	err = os.WriteFile(cm.filePath, data, 0644)
	if err != nil {
		return fmt.Errorf("写入配置文件失败: %w", err)
	}

	return nil
}

// GetConfig 获取配置
func (cm *ClientConfigManager) GetConfig() *models.ClientConfig {
	return cm.config
}

// SetConfig 设置配置
func (cm *ClientConfigManager) SetConfig(config *models.ClientConfig) error {
	cm.config = config
	return cm.validateConfig()
}

// validateConfig 验证配置
func (cm *ClientConfigManager) validateConfig() error {
	if cm.config == nil {
		return fmt.Errorf("配置不能为空")
	}

	// 验证工作模式
	if cm.config.Mode != "internal" && cm.config.Mode != "external" {
		return fmt.Errorf("无效的工作模式: %s (支持: internal/external)", cm.config.Mode)
	}

	// 验证服务器地址
	if cm.config.ServerAddr == "" {
		return fmt.Errorf("服务器地址不能为空")
	}

	// 根据模式验证相应的配置
	switch cm.config.Mode {
	case "internal":
		return cm.validateInternalConfig()
	case "external":
		return cm.validateExternalConfig()
	}

	return nil
}

// validateInternalConfig 验证内网模式配置
func (cm *ClientConfigManager) validateInternalConfig() error {
	if len(cm.config.Internal.Services) == 0 {
		return fmt.Errorf("内网模式至少需要配置一个服务")
	}

	// 检查端口冲突
	serverPortMap := make(map[int]string)

	for i, service := range cm.config.Internal.Services {
		// 验证服务名称
		if service.Name == "" {
			return fmt.Errorf("内网服务名称不能为空")
		}

		// 验证端口范围
		if service.ServerPort < 1 || service.ServerPort > 65535 {
			return fmt.Errorf("内网服务 '%s' 服务器端口号无效: %d", service.Name, service.ServerPort)
		}

		if service.TargetPort < 1 || service.TargetPort > 65535 {
			return fmt.Errorf("内网服务 '%s' 目标端口号无效: %d", service.Name, service.TargetPort)
		}

		// 检查服务器端口冲突
		if existingService, exists := serverPortMap[service.ServerPort]; exists {
			return fmt.Errorf("服务器端口 %d 冲突: 服务 '%s' 和 '%s'", service.ServerPort, service.Name, existingService)
		}
		serverPortMap[service.ServerPort] = service.Name

		// 验证目标主机
		if service.TargetHost == "" {
			cm.config.Internal.Services[i].TargetHost = "127.0.0.1"
		}

		// 验证协议
		if service.Protocol == "" {
			cm.config.Internal.Services[i].Protocol = "tcp"
		} else if service.Protocol != "tcp" && service.Protocol != "udp" {
			return fmt.Errorf("内网服务 '%s' 协议无效: %s (支持: tcp/udp)", service.Name, service.Protocol)
		}
	}

	return nil
}

// validateExternalConfig 验证外部模式配置
func (cm *ClientConfigManager) validateExternalConfig() error {
	if len(cm.config.External.Services) == 0 {
		return fmt.Errorf("外部模式至少需要配置一个服务")
	}

	// 检查端口冲突
	localPortMap := make(map[int]string)

	for i, service := range cm.config.External.Services {
		// 验证服务名称
		if service.Name == "" {
			return fmt.Errorf("外部服务名称不能为空")
		}

		// 验证端口范围
		if service.LocalPort < 1 || service.LocalPort > 65535 {
			return fmt.Errorf("外部服务 '%s' 本地端口号无效: %d", service.Name, service.LocalPort)
		}

		if service.ServerPort < 1 || service.ServerPort > 65535 {
			return fmt.Errorf("外部服务 '%s' 服务器端口号无效: %d", service.Name, service.ServerPort)
		}

		// 检查本地端口冲突
		if existingService, exists := localPortMap[service.LocalPort]; exists {
			return fmt.Errorf("本地端口 %d 冲突: 服务 '%s' 和 '%s'", service.LocalPort, service.Name, existingService)
		}
		localPortMap[service.LocalPort] = service.Name

		// 验证服务器地址
		if service.ServerAddr == "" {
			cm.config.External.Services[i].ServerAddr = cm.config.ServerAddr
		}

		// 验证协议
		if service.Protocol == "" {
			cm.config.External.Services[i].Protocol = "tcp"
		} else if service.Protocol != "tcp" && service.Protocol != "udp" {
			return fmt.Errorf("外部服务 '%s' 协议无效: %s (支持: tcp/udp)", service.Name, service.Protocol)
		}
	}

	return nil
}
